import scala.collection.mutable.ArrayBuffer

object SuperFunctionTest {
  def main(args: Array[String]): Unit = {

    // （1）map映射
    def map(arr: Array[Int], op: Int => Int) = {
      for (elem <- arr) yield op(elem)
    }

    val arr = map(Array(1, 2, 3, 4), (x: Int) => {
      x * x
    })
    println(arr.mkString(","))

    // （2）filter过滤。有参数，且参数再后面只使用一次，则参数省略且后面参数用_表示

    def filter(arr: Array[Int], op: Int => Boolean) = {
      var arr1: ArrayBuffer[Int] = ArrayBuffer[Int]()
      for (elem <- arr if op(elem)) {
        arr1.append(elem)
      }
      arr1.toArray
    }

    var arr1 = filter(Array(1, 2, 3, 4), _ % 2 == 1)
    println(arr1.mkString(","))


    // （3）reduce聚合。有多个参数，且每个参数再后面只使用一次，则参数省略且后面参数用_表示，第n个_代表第n个参数

    def reduce(arr: Array[Int], op: (Int, Int) => Int) = {

      var init: Int = arr(0)

      for (elem <- 1 until arr.length) {
        init = op(init, elem)
      }
      init
    }

    //val arr2 = reduce(Array(1, 2, 3, 4), (x, y) => x * y)
    val arr2 = reduce(Array(1, 2, 3, 4), _ * _)
    println(arr2)

    /**
     * 闭包：如果一个函数，访问到了它的外部（局部）变量的值，那么这个函数和他所处的环境，称为闭包
     * 函数柯里化：把一个参数列表的多个参数，变成多个参数列表。
     * */

    def f1() = {
      var a: Int = 10

      def f2(b: Int) = {
        a + b
      }

      f2 _
    }

    // 在调用时，f1函数执行完毕后，局部变量a应该随着栈空间释放掉
    val f = f1()

    // 但是在此处，变量a其实并没有释放，而是包含在了f2函数的内部，形成了闭合的效果
    println(f(3))
    println(f1()(3))

    // 函数柯里化，其实就是将复杂的参数逻辑变得简单化,函数柯里化一定存在闭包

  }
}
